let a: string
let b: number
let c: boolean

a = 'hello'
b = -99
c = true

console.log(a, b, c)

function count(x: number, y: number): number {
  return x + y
}

let result = count(1, 2)
console.log(result)


let str1: string // TS官方推荐的方法

str1 = 'hello'

// str1 = new String('hello') // 不能将类型“String”分配给类型“string”。  “string”是基元，但“String”是包装器对象。


let str2: String

str2 = 'hello'

str2 = new String('hello')

abstract class Package {
  // 构造方法
  constructor(public weight: number) {}

  // 抽象方法 没有具体实现
  abstract calculate(): number

  // 具体方法
  printPackage() {
    console.log(`包裹重量为：${this.weight}kg, 运费为：${this.calculate()}元`)
  }
}

class StandardPackage extends Package {
  constructor(weight: number, public unitPrice: number) {
    super(weight)
  }
  calculate(): number {
    return this.weight * this.unitPrice
  }
}

const s1 = new StandardPackage(10, 5)
s1.printPackage()


class ExpressPackage extends Package {
  constructor(weight: number, public unitPrice: number, public additional: number) {
    super(weight)
  }
  calculate(): number {
    if(this.weight > 10) return 10 * this.unitPrice + (this.weight - 10) * this.additional
    return this.weight * this.unitPrice
  }
}

const s2 = new ExpressPackage(13, 8, 2)
s2.printPackage()

interface PersonInterface {
  name: string
  age: number
  speak(n: number): void
}

class Person implements PersonInterface {
  constructor(
    public name: string,
    public age: number,
  ) {
  }

  speak(n: number): void {
    for(let i=0; i<n; i++) {
      console.log(`我是学生，我叫: ${this.name}, 今年${this.age}岁`)
    }
  }
}

const p1 = new Person('Tom', 18)
p1.speak(4)

function logData<T>(data: T) {
  console.log(data)
}

logData<number>(1)
logData<string>('abc')

interface ChildInterface<T> {
  name: string
  age: number
  extraInfo: T
}
let c1: ChildInterface<string> = {
  name: 'Andy',
  age: 12,
  extraInfo: 'good'
}

let c2: ChildInterface<number> = {
  name: 'Andy',
  age: 12,
  extraInfo: 180
}